<?php

declare(strict_types=1);

namespace So\App\Controller\Backend;

use Hyperf\HttpServer\Annotation\DeleteMapping;
use Hyperf\HttpServer\Annotation\PutMapping;
use Hyperf\HttpServer\Annotation\PostMapping;
use Psr\Http\Message\ResponseInterface;
use So\Controller\Backend;
use So\Annotation\Controller;
use Hyperf\HttpServer\Annotation\GetMapping;
use So\Annotation\Auth;
use So\Exception\ControllerException;
use So\Library\Tree;
use So\Library\Auth as AuthLib;
use Hyperf\Di\Annotation\Inject;
use So\Annotation\Validation;
use So\Annotation\Model;
use Hyperf\DbConnection\Db;
use So\Annotation\AdminLog;

/**
 * @Controller(prefix="auth_group")
 * @Auth
 * @AdminLog
 */
class AuthGroupController extends Backend
{
    /**
     * @Inject()
     * @var AuthLib
     */
    protected $auth;

    /**
     * @GetMapping("read")
     * @Model
     */
    public function read($model): ResponseInterface
    {
        $childrenGroupIds = $this->auth->getChildrenGroupIds(true);
        $groupList = $model::query()->whereIn("id", $childrenGroupIds)->get()->toArray();
        Tree::instance()->init($groupList, 'pid', ' ');
        $groupList = [];
        if ($this->auth->isSuperAdmin($this->auth->id)) {
            $groupList = Tree::instance()->getTreeList(Tree::instance()->getTreeArray(0));
        } else {
            $groups = $this->auth->getGroups($this->auth->id);
            $groupIds = [];
            foreach ($groups as $m => $n) {
                if (in_array($n['id'], $groupIds) || in_array($n['pid'], $groupIds)) {
                    continue;
                }
                $groupList = array_merge($groupList, Tree::instance()->getTreeList(Tree::instance()->getTreeArray($n['pid'])));
                foreach ($groupList as $index => $item) {
                    $groupIds[] = $item['id'];
                }
            }
        }
        return $this->success("", [
            'rows' => $groupList,
            'total' => count($groupList),
        ]);
    }

    /**
     * @PostMapping("create")
     * @Validation
     * @Model
     */
    public function create($data, $model): ResponseInterface
    {
        return parent::create($data, $model);
    }

    /**
     * @PutMapping("update")
     * @Validation
     * @Model
     */
    public function update($data, $model): ResponseInterface
    {
        return parent::update($data, $model);
    }

    /**
     * @PostMapping("operate")
     * @Model
     */
    public function operate($model): ResponseInterface
    {
        $ids = input("ids/a");
        if (in_array(1, $ids)) {
            return $this->error("超级管理员不可编辑");
        }
        return parent::operate($model);
    }

    /**
     * @DeleteMapping("delete")
     * @Model
     */
    public function delete($data, $model): ResponseInterface
    {
        return parent::delete($data, $model);
    }

    public function _delete($ids, $model): array
    {
        if (in_array(1, $ids)) {
            throw new ControllerException("不能删除超级用户组");
        }
        $grouplist = $this->auth->getGroups($this->auth->id);
        $group_ids = array_map(function ($group) {
            return $group['id'];
        }, $grouplist);
        $ids = array_diff($ids, $group_ids);
        $grouplist = $model::query()->whereIn('id', $ids)->get()->toArray();
        foreach ($grouplist as $k => $v) {
            $groupone = Db::table('auth_group_access')->where('group_id', '=', $v['id'])->first();
            if ($groupone) {
                $ids = array_diff($ids, [$v['id']]);
                continue;
            }
            $groupone = $model::query()->where('pid', '=', $v['id'])->first();
            if ($groupone) {
                $ids = array_diff($ids, [$v['id']]);
                continue;
            }
        }
        if (!$ids) {
            throw new ControllerException("不能删除有管理员的用户组");
        }
        return $ids;
    }

    public function _create($data, $model): array
    {
        $childrenGroupIds = $this->auth->getChildrenGroupIds(true);
        if (!in_array($data['pid'], $childrenGroupIds)) {
            throw new ControllerException('所选父级不存在');
        }
        $parent = $model::query()->find($data['pid']);
        if (!$parent) {
            throw new ControllerException("父级分组不存在");
        }
        $parent_rules = explode(',', $parent['rules']);
        $currentrules = $this->auth->getRuleIds($this->auth->id);
        $rules = $data['rules'];
        $rules = in_array('*', $parent_rules) ? $rules : array_intersect($parent_rules, $rules);
        $rules = in_array('*', $currentrules) ? $rules : array_intersect($currentrules, $rules);
        $data['rules'] = implode(',', $rules);
        return $data;
    }

    public function _update($data, $model): array
    {
        $childrenGroupIds = $this->auth->getChildrenGroupIds(true);
        if (!in_array($data['id'], $childrenGroupIds)) {
            throw new ControllerException('数据不存在');
        }
        if (!in_array($data['pid'], $childrenGroupIds)) {
            throw new ControllerException('所选父级不存在');
        }
        if (in_array($data['pid'], Tree::instance()->getChildrenIds($data['id'], true))) {
            throw new ControllerException("父级分组不存在");
        }
        $parent = $model::query()->find($data['pid']);
        if (!$parent) {
            throw new ControllerException("父级分组不存在");
        }
        $parent_rules = explode(',', $parent['rules']);
        $currentrules = $this->auth->getRuleIds($this->auth->id);
        $rules = $data['rules'];
        $rules = in_array('*', $parent_rules) ? $rules : array_intersect($parent_rules, $rules);
        $rules = in_array('*', $currentrules) ? $rules : array_intersect($currentrules, $rules);
        $data['rules'] = implode(',', $rules);
        $children_auth_groups = $model::query()->whereIn('id', Tree::instance()->getChildrenIds($data['id']))->get()->toArray();
        $childparams = [];
        foreach ($children_auth_groups as $key => $children_auth_group) {
            $model::query()->where("id", '=', $children_auth_group['id'])->update(['rules' => implode(',', array_intersect(explode(',', $children_auth_group['rules']), $rules))]);
        }
        return $data;
    }
}